/* 
 * File:   MainWindow.h
 * Author: jcrada
 *
 * Created on December 23, 2008, 7:39 PM
 */

#ifndef _MAINWINDOW_H
#define	_MAINWINDOW_H
#include <QtGui/QMainWindow>

#include "BulletSimulatorThread.h"
#include "QGLRendererThread.h"

#include "ui/ui_MainWindow.h"
#include "ui/ui_Inspector.h"
#include "SimulationThread.h"

namespace jcrada {

    class MainWindow : public QMainWindow {

        Q_OBJECT
    private:
        enum eForceType {
            FT_NONE = -1,
            FT_CENTRAL_FORCE, FT_CENTRAL_TORQUE,
            FT_IMPULSE_FORCE, FT_IMPULSE_TORQUE,
            FT_RELATIVE_FORCE, FT_RELATIVE_IMPULSE,
            FT_EACH_STEP,
        };
    public slots:
        virtual void changedSimulationMode( int index );
        virtual void changedCurrentTab( int tab );
        virtual void play( );
        virtual void pause( );
        virtual void togglePlay( );
        virtual void changedPlay( bool play );
        virtual void setCreatureBodyCount( int count );
        virtual void setCreatureConstraintCount( int count );
        virtual void createCreature( );
        virtual void addCreatureToWorld( );
        //from world
        virtual void onCreatureAdded( );
        virtual void onCreatureRemoved( );
        //from ui
        virtual void onBodyItemSelectionChanged( );
        virtual void onConstraintItemSelectionChanged( );

        //bodies
        virtual void duplicateForces( );
        virtual void setCreatureImpulse( double value );
        virtual void clearForces( );
        virtual void forceChanged(double value);
        virtual void applyForce( eForceType type );
        virtual void applyCentralForce( );
        virtual void applyCentralTorque( );
        virtual void applyImpulseForce( );
        virtual void applyImpulseTorque( );

        //constraints
    public:

        enum eConstraintChange {
            CC_ERP = 0, CC_ACCUMULATED_IMPULSE, CC_BOUNCE, CC_CURRENT_LIMIT,
            CC_CURRENT_LIMIT_ERROR, CC_DAMPING, CC_HI_LIMIT, CC_LIMIT_SOFTNESS,
            CC_LO_LIMIT, CC_MAX_LIMIT_FORCE, CC_MAX_MOTOR_FORCE, CC_TARGET_VELOCITY,
            CC_ENABLE,
            CC_LOWER_ANGULAR_LIMIT_X, CC_LOWER_ANGULAR_LIMIT_Y, CC_LOWER_ANGULAR_LIMIT_Z,
            CC_UPPER_ANGULAR_LIMIT_X, CC_UPPER_ANGULAR_LIMIT_Y, CC_UPPER_ANGULAR_LIMIT_Z,
        };
    public slots:
        virtual void changedConstraintMotor( );
        virtual void changedConstraint( eConstraintChange change, double value );
        virtual void changedConstraintErp( double value );
        virtual void changedConstraintAccumulatedImpulse( double value );
        virtual void changedConstraintBounce( double value );
        virtual void changedConstraintCurrentLimit( int value );
        virtual void changedConstraintCurrentLimitError( double value );
        virtual void changedConstraintDamping( double value );
        virtual void changedConstraintHiLimit( double value );
        virtual void changedConstraintLimitSoftness( double value );
        virtual void changedConstraintLoLimit( double value );
        virtual void changedConstraintMaxLimitForce( double value );
        virtual void changedConstraintMaxMotorForce( double value );
        virtual void changedConstraintTargetVelocity( double value );
        virtual void changedConstraintEnable( bool enable );
        virtual void changedConstraintLowerAngularLimitX( double value );
        virtual void changedConstraintLowerAngularLimitY( double value );
        virtual void changedConstraintLowerAngularLimitZ( double value );
        virtual void changedConstraintUpperAngularLimitX( double value );
        virtual void changedConstraintUpperAngularLimitY( double value );
        virtual void changedConstraintUpperAngularLimitZ( double value );


        //Creature
        virtual void changedCreature( int index );

        //Xml
        virtual void creatureFromClipboard( );
        virtual void creatureToClipboard( );
        virtual void showCreatureXmlMessage( bool successful );
        virtual void showPsoXmlMessage( bool successful );

        virtual void hideXmlMessages( );

        //Pso
        virtual void resetPso( );
        virtual void setPso( );

        virtual void psoFromClipboard( );
        virtual void psoToClipboard( );


    private:
        QDockWidget* _inspector;

        Ui::MainWindow* _ui_main_window;
        Ui::Inspector* _ui_inspector;

        SimulationThread* _simulation_thread;
        QGLRendererThread* _renderer_thread;

        Creature* _creature;

    protected:

        virtual void showBodyDetails( const Creature& creature, const BodyPart& body );
        virtual void showConstraintDetails( const Creature& creature, const Constraint& constraint );
        virtual void loadConstraintValues( const Constraint* constraint, const int motor_index );
        virtual void setConstraintValues( Constraint* constraint, const int motor_index,
                const eConstraintChange change, const double value );


    public:
        static int main( int argc, char** argv );
        MainWindow( QWidget* parent = NULL );
        virtual ~MainWindow( );

        virtual void createControlConnections( );
        virtual void createAppearanceConnections( );
        virtual void createCreatureConnections( );
        virtual void createPsoConnections( );
        virtual void createForcesConnections( );

        virtual void setupUi( );

        virtual void closeEvent( QCloseEvent* event );

        virtual Ui::MainWindow& getUiMainWindow( ) const {
            return *this->_ui_main_window;
        }

        virtual QDockWidget& getInspector( ) const {
            return *this->_inspector;
        }

        virtual Ui::Inspector& getUiInspector( ) const {
            return *this->_ui_inspector;
        }

        virtual SimulationThread& getSimulationThread( ) const {
            return *this->_simulator_thread;
        }

        virtual QGLRendererThread& getRendererThread( )const {
            return *this->_renderer_thread;
        }

        virtual void setCreature( Creature& creature );

        virtual Creature& getCreature( ) const {
            return *this->_creature;
        }
    };
}

#endif	/* _MAINWINDOW_H */

